﻿using System;
using SdmxMl.Structure;
using System.Windows.Forms;
using SdmxMl.Panels;
using SdmxMl.Common;
using SdmxMl.Manager;


namespace SdmxMl.UC
{
    /// <summary>
    /// Class for editing Target Identifiers of MSD Reports
    /// </summary>
    public partial class UcMetadataTarget : UserControl
    {

        #region Internal Members

        private TargetIdentifiersType _targetIdentifiers = null;
        private TreeNode treeNode;
        private bool _isFinal;
        private UcMlText ucMlText = null;
        private UcMlText ucMlTextIdentCompo = null;
        private UcMlText ucMlTextPartialIdent = null;
        private PanelAnnotationList pannelAnnot;
        private IdentifierComponentType _identifierCompo;
        private PartialTargetIdentifierType _partialIdentifier;
        private bool listComponentOnUpdate;

        #endregion //Internal Members

        #region Constructor

        public UcMetadataTarget()
        {
            InitializeComponent();

            ucMlText = new UcMlText();
            customComboBoxName.DropDownControl = ucMlText;

            ucMlTextIdentCompo = new UcMlText();
            customComboBoxIdentCompo.DropDownControl = ucMlTextIdentCompo;

            ucMlTextPartialIdent = new UcMlText();
            customComboBoxPartialName.DropDownControl = ucMlTextPartialIdent;


            // Full identifiers
            comboBoxIdentCompoTarget.Items.Clear();
            foreach (ObjectTypeCodelistType o in Enum.GetValues(typeof(ObjectTypeCodelistType)))
                comboBoxIdentCompoTarget.Items.Add(o.ToString());

            tabPageMetadataTarget.BackColor = System.Drawing.Color.AliceBlue;

        }

        #endregion //Constructor

        #region Binding

        public void BindFromNode(TreeNode node, PanelAnnotationList panelAnnotation, bool isFinal)
        {
            pannelAnnot = panelAnnotation;
            _isFinal = isFinal;
            buttonRefSchemeError.Visible = false;
            treeNode = node;
            _targetIdentifiers = null;
            if (node != null)
                _targetIdentifiers = node.Tag as TargetIdentifiersType;
            BindToControls();
        }

        public bool UpdateNodeTag(TreeNode node)
        {
            if (node != null)
            {
                BindFromControls();
                if (_targetIdentifiers != null)
                    node.Text = _targetIdentifiers.ToString();
            }

            return false; // true on error
        }

        // No edition if Parent Artefact IsFinal
        private void IsFinalEditControls(bool isFinal)
        {
            bool enabled = isFinal == false;

            textBoxId.ReadOnly = isFinal;
            textBoxUrn.ReadOnly = isFinal;
            textBoxUri.ReadOnly = isFinal;
            customComboBoxName.IsFinal = isFinal;
            comboMultiLinesDescr.IsFinal = isFinal;

            comboBoxIdentCompoTarget.Enabled = enabled;
            customComboBoxIdentCompo.IsFinal = isFinal;
            comboMultiLinesIdentCompoDescr.IsFinal = isFinal;
            textBoxIdentCompo.ReadOnly = isFinal;
            textBoxIdentCompoUri.ReadOnly = isFinal;
            textBoxIdentCompoUrn.ReadOnly = isFinal;
            buttonClrRepScheme.Enabled = enabled;

        }

        private void BindToControls()
        {
            if (_targetIdentifiers != null)
            {
                Visible = true;
                textBoxId.Text = _targetIdentifiers.FullTargetIdentifier.Id;
                textBoxUrn.Text = _targetIdentifiers.FullTargetIdentifier.Urn;
                textBoxUri.Text = _targetIdentifiers.FullTargetIdentifier.Uri;
                customComboBoxName.Text = _targetIdentifiers.FullTargetIdentifier.Name.ToString();
                ucMlText.ML = _targetIdentifiers.FullTargetIdentifier.Name;
                comboMultiLinesDescr.Text = _targetIdentifiers.FullTargetIdentifier.Description.ToString();
                comboMultiLinesDescr.ML = _targetIdentifiers.FullTargetIdentifier.Description;

                ConstructListComponents(_identifierCompo);

                ConstructPartialList(_partialIdentifier);

                UpdateAnnotation();
                IsFinalEditControls(_isFinal);
                
            }
            else
            {
                Visible = false;
            }
        }

        private void BindFromControls()
        {
            if (_targetIdentifiers != null)
            {
                _targetIdentifiers.FullTargetIdentifier.Id = textBoxId.Text;
                _targetIdentifiers.FullTargetIdentifier.Urn = textBoxUrn.Text;
                _targetIdentifiers.FullTargetIdentifier.Uri = textBoxUri.Text;
                _targetIdentifiers.FullTargetIdentifier.Name.UpdateForCurrentLanguage(customComboBoxName.Text);
                _targetIdentifiers.FullTargetIdentifier.Description.UpdateForCurrentLanguage(comboMultiLinesDescr.Text);

                // Update Full references
                UpdateIdentifierCompoFromDetail();
                _targetIdentifiers.FullTargetIdentifier.IdentifierComponentList.Clear();
                foreach (IdentifierComponentType ic in listBoxComponents.Items)
                    _targetIdentifiers.FullTargetIdentifier.IdentifierComponentList.Add(ic);

                // Update partial references
                UpdatePartialIdentifierFromDetail();
                _targetIdentifiers.PartialTargetIdentifierList.Clear();
                foreach (PartialTargetIdentifierType pti in listBoxPartialIdent.Items)
                    _targetIdentifiers.PartialTargetIdentifierList.Add(pti);

                // and partial content according to full target list
                foreach (IdentifierComponentType ic in _targetIdentifiers.FullTargetIdentifier.IdentifierComponentList)
                    foreach (PartialTargetIdentifierType pti in _targetIdentifiers.PartialTargetIdentifierList)
                        if (pti.IdentifierComponentRef.Contains(ic.Id) == false)
                            pti.IdentifierComponentRef.Remove(ic.Id);

            }
        }

        #endregion

        #region Full List Events

        private void ConstructListComponents(object objToSelect)
        {

            listBoxComponents.Items.Clear();
            // Simple list in tree
            listComponentOnUpdate = true;
            foreach (IdentifierComponentType ic in _targetIdentifiers.FullTargetIdentifier.IdentifierComponentList)
                listBoxComponents.Items.Add(ic);

            // Locate existing (if any)
            foreach (IdentifierComponentType ic in listBoxComponents.Items)
            {
                if (ic == _identifierCompo)
                {
                    listBoxComponents.SelectedItem = ic;
                    break;
                }
            }
            if (_identifierCompo == null && listBoxComponents.Items.Count > 0)
            {
                listBoxComponents.SelectedIndex = 0;
            }
            listComponentOnUpdate = false;
            UpdateControlsFromTreeSelected();

        }

        private void listBoxComponents_SelectedIndexChanged(object sender, EventArgs e)
        {
            // Avoid recursion
            if (listComponentOnUpdate)
                return;
            // Update current item from detail view
            UpdateIdentifierCompoFromDetail();

            //Update controls for new one
            UpdateControlsFromTreeSelected();
        }

        private void UpdateIdentifierCompoFromDetail()
        {
            // Update current item if exists
            if (_identifierCompo != null)
            {
                // Update selected
                _identifierCompo.Id = textBoxIdentCompo.Text;
                _identifierCompo.Name.UpdateForCurrentLanguage(customComboBoxIdentCompo.Text);
                if (comboBoxIdentCompoTarget.SelectedIndex >= 0)
                    _identifierCompo.TargetObjectClass = (ObjectTypeCodelistType)Enum.Parse(typeof(ObjectTypeCodelistType),
                    comboBoxIdentCompoTarget.Items[comboBoxIdentCompoTarget.SelectedIndex].ToString(), true);

                _identifierCompo.Uri = textBoxIdentCompoUri.Text;
                _identifierCompo.Urn = textBoxIdentCompoUrn.Text;
            }

        }
        private void UpdateControlsFromTreeSelected()
        {
            //Reset
            _identifierCompo = null;
            textBoxRepresentationScheme.Text = string.Empty;

            if (listBoxComponents.SelectedIndex >= 0)
            {
                groupBoxComponent.Visible = true;
                _identifierCompo = listBoxComponents.Items[listBoxComponents.SelectedIndex] as IdentifierComponentType;
                if (_identifierCompo != null)
                {
                    comboMultiLinesIdentCompoDescr.ML = _identifierCompo.Description;

                    ucMlTextIdentCompo.ML = _identifierCompo.Name;
                    customComboBoxIdentCompo.Text = _identifierCompo.Name.ToString();

                    textBoxIdentCompo.Text = _identifierCompo.Id;
                    textBoxIdentCompoUri.Text = _identifierCompo.Uri;
                    textBoxIdentCompoUrn.Text = _identifierCompo.Urn;
                    textBoxRepresentationScheme.Text = _identifierCompo.RepresentationScheme.ToString();
                    buttonRefSchemeError.Visible = false;

                    comboBoxIdentCompoTarget.SelectedIndex = (int)_identifierCompo.TargetObjectClass;

                }
            }
            else 
                groupBoxComponent.Visible = false;

            toolStripButtonDeleteComponent.Enabled = _isFinal == false && _identifierCompo != null;
            toolStripButtonAddComponent.Enabled = _isFinal == false;
            toolStripButtonRepresentationScheme.Enabled = _isFinal == false && _identifierCompo != null;

            UpdateNavigationRefErrorButton();
            UpdateAnnotation();

        }

        #endregion // List Events

        #region Annotations

        private void UpdateAnnotation()
        {
            if (tabControlTargets.SelectedIndex == 0)
                pannelAnnot.BindFromNode(_targetIdentifiers, _isFinal);
            else if (tabControlTargets.SelectedIndex == 1)
                pannelAnnot.BindFromNode(_identifierCompo, _isFinal);
            else if (tabControlTargets.SelectedIndex == 2)
                pannelAnnot.BindFromNode(_partialIdentifier, _isFinal);
        }

        #endregion //Annotations

        #region Detail Controls Events

        // Refresh Tree currently selected item label
        private void textBoxIdentCompo_TextChanged(object sender, EventArgs e)
        {
            if (_identifierCompo != null)
            {
                _identifierCompo.Id = textBoxIdentCompo.Text;
                listComponentOnUpdate = true;
                listBoxComponents.RefreshItem(listBoxComponents.SelectedIndex);
                listComponentOnUpdate = false;
            }
        }

        /// <summary>
        /// Visible if reference not found
        /// </summary>
        private void UpdateNavigationRefErrorButton()
        {
            bool vis = textBoxRepresentationScheme.Text.Length > 0;
            if (_identifierCompo != null && textBoxRepresentationScheme.Text.Length > 0)
                vis = GetNavigateArtefact(_identifierCompo.RepresentationScheme) == null;
            
            buttonRefSchemeError.Visible = vis;
        }

        private Artefact GetNavigateArtefact(RepresentationSchemeType repScheme)
        {
            ArtefactList artefactList = ReferenceManager.GetArtefactList(repScheme.DetermineArtefactType());
            Artefact ar = ReferenceManager.LocateArtefact(artefactList, _identifierCompo.RepresentationScheme);
            return ar;
        }

        private void buttonNavigate_Click(object sender, EventArgs e)
        {
            if (_identifierCompo != null)
            {
                try
                {
                    SdmxArtefactType arType = _identifierCompo.RepresentationScheme.DetermineArtefactType();
                    if (arType != SdmxArtefactType.None)
                    {
                        ArtefactRefTyped art = new ArtefactRefTyped(arType, _identifierCompo.RepresentationScheme.FullIdent);

                        // If already in memory, navigate otherwhile get from registry
                        if (NavigationManager.LocatenavigateProject(art.Type, art.FullIdent, null) == null)
                            NavigationManager.NavigateWithRegistry(art.Type, art.FullIdent, true, null);
                    }
                }
                catch { }
            }
        }

        #endregion // Detail Controls Events

        #region ToolStrip Events
        private void DeleteItemFromList(ListBox listBox)
        {
            if (MessageBox.Show(string.Format("Delete selected item ({0})?",
                listBox.SelectedItem.ToString()), "Check",
                MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                int index = listBox.SelectedIndex;
                listBox.Items.Remove(listBox.SelectedItem);
                if (listBox.Items.Count > 0)
                {
                    if (index > 0)
                        --index;
                    listBox.SelectedIndex = index;
                }
            }
        }

        private void listBoxComponents_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Delete)
            {
                ListBox lb = sender as ListBox;
                if (lb != null && lb.SelectedIndex != -1)
                {
                    DeleteItemFromList(lb);

                    e.Handled = true;
                }
            }
        }

        private void toolStripButtonDeleteComponent_Click(object sender, EventArgs e)
        {
            DeleteItemFromList(listBoxComponents);
        }

        private void toolStripButtonAddComponent_Click(object sender, EventArgs e)
        {
            IdentifierComponentType ic = new IdentifierComponentType();
            ic.Id = "Undefined";
            listBoxComponents.Items.Add(ic);
            listBoxComponents.SelectedItem = ic;

        }
        

        private void toolStripButtonRepresentationScheme_Click(object sender, EventArgs e)
        {
            RepresentationSchemeType copy = _identifierCompo.RepresentationScheme.Clone();
            DlgEditReferenceType aDlg = new DlgEditReferenceType(copy);
            if (aDlg.ShowDialog() == DialogResult.OK)
            {
                _identifierCompo.RepresentationScheme = copy;
                textBoxRepresentationScheme.Text = _identifierCompo.RepresentationScheme.ToString();
                UpdateNavigationRefErrorButton();
            }
        }

        #endregion //ToolStrip Events

        #region Partial Identifier list 

        private void ConstructPartialList(object objToSelect)
        {
            listBoxPartialIdent.Items.Clear();
            listComponentOnUpdate = true;
            foreach (PartialTargetIdentifierType ic in _targetIdentifiers.PartialTargetIdentifierList)
                listBoxPartialIdent.Items.Add(ic);

            // Locate existing (if any)
            foreach (PartialTargetIdentifierType ic in listBoxPartialIdent.Items)
            {
                if (ic == objToSelect)
                {
                    listBoxPartialIdent.SelectedItem = ic;
                    break;
                }
            }
            if (_partialIdentifier == null && listBoxPartialIdent.Items.Count > 0)
                listBoxPartialIdent.SelectedIndex = 0;

            listComponentOnUpdate = false;
            UpdatePartialSelected();
        }


        private void listBoxPartialIdent_SelectedIndexChanged(object sender, EventArgs e)
        {
            // Avoid recursion
            if (listComponentOnUpdate)
                return;
            // Update current item from detail view
            UpdatePartialIdentifierFromDetail();

            //Update controls for new one
            UpdatePartialSelected();
        }


        private void toolStripButtonAddPartial_Click(object sender, EventArgs e)
        {
            PartialTargetIdentifierType ic = new PartialTargetIdentifierType();
            ic.Id = "Undefined";
            listBoxPartialIdent.Items.Add(ic);
            listBoxPartialIdent.SelectedItem = ic;

        }

        private void toolStripButtonRemovePartial_Click(object sender, EventArgs e)
        {
            DeleteItemFromList(listBoxPartialIdent);
        }

        private void UpdatePartialIdentifierFromDetail()
        {
            // Update current item if exists
            if (_partialIdentifier != null)
            {
                // Update selected
                _partialIdentifier.Id = textBoxPartialId.Text;
                _partialIdentifier.Name.UpdateForCurrentLanguage(customComboBoxPartialName.Text);
                _partialIdentifier.Uri = textBoxPartialUri.Text;
                _partialIdentifier.Urn = textBoxPartialUrn.Text;

                _partialIdentifier.IdentifierComponentRef.Clear();
                foreach (string s in ucDualListRef.ListAssigned.Items)
                    _partialIdentifier.IdentifierComponentRef.Add(s);
            }

        }

        private void UpdatePartialSelected()
        {
            //Reset
            _partialIdentifier = null;
            ucDualListRef.ListAssigned.Items.Clear();
            ucDualListRef.ListAvailable.Items.Clear();

            if (listBoxPartialIdent.SelectedIndex >= 0)
            {
                groupBoxPartial.Visible = true;
                _partialIdentifier = listBoxPartialIdent.Items[listBoxPartialIdent.SelectedIndex] as PartialTargetIdentifierType;
                if (_partialIdentifier != null)
                {
                    comboMultiLinesPartialDescr.ML = _partialIdentifier.Description;

                    ucMlTextPartialIdent.ML = _partialIdentifier.Name;
                    customComboBoxPartialName.Text = _partialIdentifier.Name.ToString();

                    textBoxPartialId.Text = _partialIdentifier.Id;
                    textBoxPartialUri.Text = _partialIdentifier.Uri;
                    textBoxPartialUrn.Text = _partialIdentifier.Urn;

                    foreach (IdentifierComponentType ic in listBoxComponents.Items)
                        if ( _partialIdentifier.IdentifierComponentRef.Contains(ic.Id))
                            ucDualListRef.ListAssigned.Items.Add(ic.Id);
                        else
                            ucDualListRef.ListAvailable.Items.Add(ic.Id);

                }
            }
            else
                groupBoxPartial.Visible = false;

            toolStripButtonRemovePartial.Enabled = _isFinal == false && _partialIdentifier != null;
            toolStripButtonAddPartial.Enabled = _isFinal == false;

            UpdatePartialRefButtonsState();
            UpdateAnnotation();

        }

        private void UpdatePartialRefButtonsState()
        {
            ucDualListRef.Enabled = _isFinal == false;

        }

        private void textBoxPartialId_TextChanged(object sender, EventArgs e)
        {
            if (listBoxPartialIdent.SelectedItem is PartialTargetIdentifierType)
            {
                PartialTargetIdentifierType ic = listBoxPartialIdent.SelectedItem as PartialTargetIdentifierType;
                ic.Id = textBoxPartialId.Text;
                listComponentOnUpdate = true;
                UpdateListBoxItem(listBoxPartialIdent, ic);
                listComponentOnUpdate = false;

            }
        }

        /// <summary>Helper method without using RefreshingListbox </summary>
        /// <param name="lb">listbox to refresh</param>
        /// <param name="item">modified item</param>
        private void UpdateListBoxItem(ListBox lb, object item)
        {
            int index = lb.Items.IndexOf(item);
            int currIndex = lb.SelectedIndex;
            lb.BeginUpdate();
            try
            {
                lb.Items[index] = item;
            }
            finally
            {
                lb.EndUpdate();
            }
        }  

        #endregion //Partial Identifier list

        #region TabControl Event

        private void tabControlTargets_SelectedIndexChanged(object sender, EventArgs e)
        {
            BindFromControls();
            if (tabControlTargets.SelectedIndex == 2)
                UpdatePartialSelected();
            else
                UpdateAnnotation();

        }
        #endregion

        #region URI change

        private void buttonNavigateUri_Click(object sender, EventArgs e)
        {
            try
            {
               // System.Diagnostics.Process myProc;
          //      myProc = System.Diagnostics.Process.Start(c.Uri);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void textBoxUri_TextChanged(object sender, EventArgs e)
        {
            // External Navigation Command
         //   c.Uri = textBoxUri.Text;
            buttonNavigateUri.Visible = textBoxUri.Text.Length > 0;

        }

        #endregion

        #region Clear Representation ref

        private void buttonClrRepScheme_Click(object sender, EventArgs e)
        {
            if (_identifierCompo != null)
            {
                _identifierCompo.RepresentationScheme = new RepresentationSchemeType();
                textBoxRepresentationScheme.Text = _identifierCompo.RepresentationScheme.ToString();
            }

        }

        #endregion

    }
}
